/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.gobygang.server;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;

import org.apache.tools.ant.taskdefs.email.Mailer;

import com.gobygang.shared.ChitInfo;
import com.gobygang.shared.LoginInfo;
import com.gobygang.shared.RouteInfo;
import com.gobygang.shared.TaxiGangInfo;
import com.gobygang.shared.TaxiGangInfo.LeaveResult;
import com.gobygang.shared.TaxiGanguserInfo;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;

/**
 *
 * @author hall
 */
public class TaxiGangManager {
	
	boolean useChannel = false;

	private TaxiGangDAO taxiGangDAO;
	private TaxiGangUserDAO taxiGangUserDAO ;
	private TaxiCompanyDAO taxiCompanyDAO ;
	private PartnerDAO partnerDAO ;

	private EntityManager em ;

	public TaxiGangManager(){
		em = EMF.get().createEntityManager();
		taxiGangDAO = new TaxiGangDAO(em);
		taxiGangUserDAO = new TaxiGangUserDAO(em);
		partnerDAO = new PartnerDAO(em);
	}

	public TaxiGangDAO getTaxiGangDAO(){
		return taxiGangDAO;
	}
	public TaxiGangUserDAO getTaxiGangUserDAO(){
		return taxiGangUserDAO;
	}
	//private LoginRecordDAO loginRecordDAO = new LoginRecordDAO();
	private ChitDAO chitDAO = new ChitDAO();
	//private TaxiCompanyDAO taxiCompanyDAO = new TaxiCompanyDAO();


	public TaxiGangInfo[] getTaxiGangs(TaxiGangInfo taxiganginfo, Date now){
		Mailer.search(taxiganginfo);

		return taxiGangDAO.getTaxiGangsByProximity(taxiganginfo,now);

	} // end method getTaxiGangs


	public TaxiGangInfo[] getMyTaxiGangs(LoginInfo loginInfo){
		return getMyTaxiGangs(loginInfo, new Date());
	}

	public TaxiCompanyInfo[] getTaxiCompanyList(TaxiGangInfo taxiGangInfo){
		return taxiCompanyDAO.find(taxiGangInfo);
	}
	public void createTaxiCompany(TaxiCompanyInfo taxiCompanyInfo){
		taxiCompanyDAO.create(taxiCompanyInfo);
	}
	public TaxiGangInfo[] getMyTaxiGangs(LoginInfo loginInfo, Date now){
		//Log.info("TaxiGangManager.getMyTaxiGangs:"+loginInfo.getId());
		TaxiGanguser taxiganguser=taxiGangUserDAO.get(loginInfo.getId());

		TaxiGangInfo[] myTaxiGangs = taxiGangDAO.getTaxiGangByUser(taxiganguser);
		List<TaxiGangInfo>filterList = new ArrayList<TaxiGangInfo>();
		for (TaxiGangInfo info : myTaxiGangs){
			TaxiGangInfo provisional = taxiGangUserDAO.getMembers(info,taxiganguser.getId());
			if (!"DONT_SHOW".equals(provisional.getStatus())){
				filterList.add( provisional );				
			}
		}
		return filterList.toArray(new TaxiGangInfo[0]);

	} // end method getTaxiGangs


	public void createTaxiGang(TaxiGangInfo taxiganginfo, LoginInfo loginInfo, ChitInfo chitInfo) {
		getTaxiGang(taxiganginfo,loginInfo,chitInfo);
	}

	public void createWishRoute(TaxiGangInfo taxiganginfo, LoginInfo loginInfo) {
		//Log.info("TaxiGangManager.getTaxiGang:"+loginInfo.getId());
		TaxiGanguserInfo leaderInfo=taxiGangUserDAO.getInfo(loginInfo);

		wishRouteDAO.add(taxiganginfo, loginInfo);
	}

	public void cancelWishRoute(String wishRouteId) {
		//Log.info("TaxiGangManager.cancelWishRoute:"+wishRouteId);

		wishRouteDAO.delete(wishRouteId);
	}


	public Collection<WishRouteInfo> findWishRoutes(TaxiGangInfo taxiganginfo){
		return wishRouteDAO.find(taxiganginfo);
	}

	public TaxiGangInfo getTaxiGang(TaxiGangInfo taxiGangInfo, LoginInfo loginInfo, ChitInfo chitInfo) {
		//Log.info("TaxiGangManager.getTaxiGang:"+loginInfo.getId());
		TaxiGanguserInfo leaderInfo=taxiGangUserDAO.getInfo(loginInfo);

		TaxiGangInfo taxigangInfo = taxiGangDAO.add(taxiGangUserDAO,leaderInfo, taxiGangInfo, chitInfo, loginInfo);
		if (chitInfo != null){
			//chitDAO.add(taxigangInfo, leader, chitInfo.getChitText());
		}
//		if (false){
//			//TODO remove this once taxicompany entered
//			TaxiCompanyInfo taxiCompanyInfo = new TaxiCompanyInfo();
//			taxiCompanyInfo.setLatLng(48.138, 11.53);
//			taxiCompanyInfo.setName("Peters Taxi Co.");
//			taxiCompanyInfo.setUrl("www.hall-services.de");
//
//			taxiCompanyDAO.create(taxiCompanyInfo);
//		}
		return taxigangInfo;
	}

	public TaxiGangInfo getInvitation(String invitation) {
		TaxiGangInfo taxiGangInvitation=taxiGangDAO.getTaxiGang(invitation);
		return taxiGangInvitation;
	}

	public RouteInfo getPartner(String partnerId) {
		//TODO remove
		/**
		RouteInfo info = new RouteInfo();   
		info.setId("1234");
		info.setLat(48);
		info.setLng(11);
		info.setDestination("Munich, Germany");
		createPartner(info);
		*/
	
		RouteInfo partnerInfo=partnerDAO.find(partnerId);
		return partnerInfo;
	}

	public RouteInfo getRoute(String ref) {
		//TODO remove
		
//		RouteInfo info = new RouteInfo();
//		info.setName("Kirsten's");
//		info.setStartCity("Munich");
//		info.setStartAddress("Westendstr 80");
//		info.setDestinationCity("Munich");
//		info.setDestinationAddress("Kleinstr 42");
//		createRoute(info);
		
		RouteInfo partnerInfo=routeDAO.find(ref);
		return partnerInfo;
	}

	public void createPartner(RouteInfo partnerInfo) {
		partnerDAO.create(partnerInfo);
	}

	public void createRoute(RouteInfo partnerInfo) {
		routeDAO.create(partnerInfo);
	}

	public void joinTaxiGang(TaxiGangInfo taxiganginfo, LoginInfo loginInfo, ChitInfo chitInfo) {
		TaxiGanguserInfo taxiganguserInfo=taxiGangUserDAO.getInfo(loginInfo);
		//Log.info("joinTaxiGang for uid="+taxiganguserInfo.getId()+ " display name="+taxiganguserInfo.getDisplayName());

		TaxiGangInfo taxigangInfo = taxiGangDAO.get(taxiGangUserDAO,taxiganginfo.getId());

		taxiGangDAO.addMessage(taxigangInfo, chitInfo);

		TaxiGanguser user = taxiGangUserDAO.get(taxiganguserInfo.getId());
		taxiGangDAO.setMember(taxigangInfo, user);

		taxiGangUserDAO.addToMyTaxiGangs(loginInfo.getId(), taxiganginfo.getId());

		taxiGangDAO.inform(taxigangInfo, Inform.JOIN, loginInfo);
		String name = loginInfo.getNickname();
		Mailer.sendMessage("A taxigang was joined by "+name,taxiganginfo,loginInfo);


	}

	public LeaveResult leaveTaxiGang(TaxiGangInfo taxiganginfo, LoginInfo loginInfo) {
		//Log.info("TaxiGangManager.leaveTaxiGang:"+loginInfo.getId());
		TaxiGanguserInfo taxiganguserInfo=taxiGangUserDAO.getInfo(loginInfo);

		TaxiGanguser user = taxiGangUserDAO.get(taxiganguserInfo.getId());

		LeaveResult leaveResult = taxiGangDAO.leave(taxiganginfo, user);

		if (leaveResult==LeaveResult.OK){

			taxiGangUserDAO.removeFromMyTaxiGangs(loginInfo.getId(), taxiganginfo.getId());
		}

		taxiGangDAO.inform(taxiganginfo, Inform.LEAVE, loginInfo);
		Mailer.sendMessage("A taxigang was left by ",taxiganginfo,loginInfo);
		return leaveResult;

	}

	public TaxiGanguserInfo getTaxiGangUser(LoginInfo loginInfo){
		//Log.info("TaxiGangManager.getTaxiGangUser:"+loginInfo.getId());
		//loginRecordDAO.create(loginInfo);

		TaxiGanguserInfo taxiGanguserInfo = taxiGangUserDAO.getInfo(loginInfo);
		if (useChannel){
		String channelToken = null;
		try{
			ChannelService channelService = ChannelServiceFactory.getChannelService();
			channelToken = channelService.createChannel(taxiGanguserInfo.getId()); 	
			//Log.info("TaxiGangManager.getTaxiGangUser:channelToken:"+channelToken);
		} catch (Exception ex){
			//Log.error("error creating channel for id="+taxiGanguserInfo.getId());
		}
		taxiGanguserInfo.setChannelToken(channelToken);
		}
		return taxiGanguserInfo;
	}


	public void deleteAllTaxiGangUsers(){
		taxiGangUserDAO.deleteAll();
	}

	public void deleteAllTaxiGangs(){
		taxiGangDAO.deleteAll();
	}


	public void deleteTaxiGang(TaxiGangInfo taxiganginfo){
		taxiGangDAO.remove(taxiganginfo);
	}

	public void addMessage(TaxiGangInfo taxiganginfo, LoginInfo loginInfo, String message ) {
		//Log.info("TaxiGangManager:addMessage:uid="+loginInfo.getId()+"message"+message);

		TaxiGangInfo taxigangInfo = taxiGangDAO.get(taxiGangUserDAO,taxiganginfo.getId());
		ChitInfo chitInfo = new ChitInfo(message, new Date(), loginInfo.getNickname(), loginInfo.getMobilenumber());
		taxiGangDAO.addMessage(taxigangInfo,chitInfo);
		//chitDAO.add(taxigangInfo, taxiganguserInfo, message);
		taxiGangDAO.inform(taxiganginfo, Inform.MESSAGE, loginInfo);
		Mailer.sendMessage("A message was sent by :"+loginInfo.getNickname()+":"+message,taxiganginfo,loginInfo);


	}

	public double getAffinity(TaxiGangInfo taxiganginfo1, TaxiGangInfo taxiganginfo2){

		double affinity =  	Math.abs(taxiganginfo1.getStartLat() - taxiganginfo2.getStartLat());
		affinity +=  		Math.abs(taxiganginfo1.getStartLng() - taxiganginfo2.getStartLng());
		affinity +=  		Math.abs(taxiganginfo1.getDestinationLat() - taxiganginfo2.getDestinationLat());
		affinity +=  		Math.abs(taxiganginfo1.getDestinationLng() - taxiganginfo2.getDestinationLng());
		return affinity;
	}

	//	public TaxiGanguser getTaxiGangUser(LoginInfo loginInfo){
	//		//Log.info("TaxiGangManager:getTaxiGangUser:uid="+loginInfo.getId()+"message");
	//		loginRecordDAO.create(loginInfo);
	//		return taxiGangUserDAO.get(loginInfo);
	//	}

	public TaxiGanguserInfo getTaxiGangUserInfo(LoginInfo loginInfo){
		//Log.info("TaxiGangManager:getTaxiGangUser:uid="+loginInfo.getId()+"message");
		//loginRecordDAO.create(loginInfo);
		return taxiGangUserDAO.getInfo(loginInfo);
	}

	public void award(TaxiGangInfo taxiganginfo,String userId) {
		taxiGangUserDAO.award(taxiganginfo,userId,taxiGangDAO);

	}

	public void expireTaxiGang(TaxiGangInfo  taxiGangInfo){
		taxiGangDAO.expire(taxiGangInfo);
	}

	public void runPermanents() {
		taxiGangDAO.resetPermanents();
	}
}
